/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "parser/file_type_parser_default.h"
#include "imageknife_task_internal.h"
#include "downsampling/down_sampler.h"
#include "imageknife_internal.h"
#include "request/imageknife_request_internal.h"
#include "utils/file_type_util.h"
#include <sstream>

namespace ImageKnifePro {

ImageKnifeTaskInternal::ImageKnifeTaskInternal(std::shared_ptr<uint8_t[]> buffer, uint32_t bufferLength,
    uint32_t frameIndex, ImageRequestType type, std::shared_ptr<ImageKnifeRequestInternal> request)
    : frameIndex_(frameIndex), type_(type), request_(request), isFrameDecodeMode_(true)
{
    product.imageBuffer = buffer;
    product.imageLength = bufferLength;
}

ImageKnifeTaskInternal::ImageKnifeTaskInternal(std::shared_ptr<ImageKnifeTaskInternal> task)
{
    // 使用旧task部分属性构造
    jobKey = task->jobKey;
    traceId = task->traceId;
    fallbackUrlIndex = task->fallbackUrlIndex;
    memoryKey = task->memoryKey;
    fileKey = task->fileKey;
    foundFileCache = task->foundFileCache;
    promiseSyncLoad = task->promiseSyncLoad;
    imageSrc_ = task->imageSrc_;
    imageSrcBack_ = imageSrc_;

    // 未拷贝decode src，不涉及相关阶段
    request_ = task->request_;
    type_ = task->type_;
    lastError_ = task->lastError_;

    fileCacheNeedRename_ = task->fileCacheNeedRename_;
    isAnimator_ = task->isAnimator_;

    product = task->product;
    httpCode = task->httpCode;
}

ImageKnifeTaskInternal::ImageKnifeTaskInternal(std::shared_ptr<ImageKnifeTaskInternal> task, const IJobQueue::Job &job)
    : ImageKnifeTaskInternal(task)
{
    traceId = job.jobId;
    memoryKey = job.memoryKey;
    request_ = job.request;
    type_ = job.type;
}

void ImageKnifeTaskInternal::Detach()
{
    isDetached_ = true;
}

bool ImageKnifeTaskInternal::IsDetached()
{
    return isDetached_;
}

std::string ImageKnifeTaskInternal::GetTaskInfo(ImageRequestType type,
                                                std::shared_ptr<ImageKnifeRequestInternal> request)
{
    IMAGE_KNIFE_CHECK_RETURN(request == nullptr, "[Null Request] ");

    std::string source;
    switch (type) {
        case ImageRequestType::MAIN_SRC:
            source = "MainSrc";
            break;
        case ImageRequestType::PLACE_SRC:
            source = "PlaceSrc";
            break;
        case ImageRequestType::THUMBNAIL_SRC:
            source = "ThumbnailSrc";
            break;
        case ImageRequestType::ERROR_SRC:
            source = "ErrorSrc";
            break;
        default:
            break;
    }

    if (request->IsPreload()) {
        return "[ID:" + request->GetNodeId() + " Animator:" + std::to_string(request->IsPreloadAnimator()) +
               " Type:" + source + "] ";
    }

    return "[ID:" + request->GetNodeId() + " VersionID:" + std::to_string(request->GetVersion()) +
           " Type:" + source + "] ";
}

std::string ImageKnifeTaskInternal::GetTaskInfo() const
{
    return GetTaskInfo(type_, request_);
}

std::string ImageKnifeTaskInternal::GetDisplayPixelmapInfo() const
{
    IMAGE_KNIFE_CHECK_RETURN(product.imageDataCache == nullptr, "Null Image DataCache");
    auto dataCache = std::dynamic_pointer_cast<ImageDataCacheInternal>(product.imageDataCache);
    IMAGE_KNIFE_CHECK_RETURN(dataCache == nullptr, "Null Image DataCacheInternal");
    auto pixelmapSize = dataCache->GetPixelmapSize();
    std::ostringstream res;
    res << " Pixelmap Ready, origin width:" << dataCache->imageWidth << " origin height:" << dataCache->imageHeight
        << " pixelmap width:" << pixelmapSize.width << " pixelmap height:" << pixelmapSize.height
        << " cache size:" << dataCache->GetImageCacheSize() << " format:" << static_cast<int>(dataCache->type);
    return res.str();
}

void ImageKnifeTaskInternal::SetIsAnimator()
{
    IMAGE_KNIFE_CHECK(request_ == nullptr);
    if (request_->IsPreload()) {
        isAnimator_ = request_->IsPreloadAnimator();
        return;
    }

    auto imageNode = ImageKnifeInternal::GetInstance().GetImageNode(request_->GetNodeId());
    if (imageNode != nullptr) {
        isAnimator_ = imageNode->IsAnimator();
        return;
    }

    // 预创建组件非Animator组件
    isAnimator_ = false;
}

ImageFormat ImageKnifeTaskInternal::GetImageBufferFormat() const
{
    if (fileTypeInfo_ == nullptr) {
        return ImageFormat::UNKNOWN;
    }
    return fileTypeInfo_->format;
}

ImageSource *ImageKnifeTaskInternal::GetImageSource() const
{
    return imageSrc_;
}

ImageRequestType ImageKnifeTaskInternal::GetImageRequestType() const
{
    return type_;
}

std::shared_ptr<ImageKnifeRequest> ImageKnifeTaskInternal::GetImageKnifeRequest() const
{
    return request_;
}

void ImageKnifeTaskInternal::SetDecodeImageSource(std::shared_ptr<DecodeImageSource> decodeImageSource)
{
    // 逐帧解码专用task才会调用该函数
    if (decodeImageSource == nullptr) {
        EchoError("Get Empty DecodeImageSource");
        return;
    }

    decodeImageSource_ = decodeImageSource;
}

std::shared_ptr<DecodeImageSource> ImageKnifeTaskInternal::GetDecodeImageSource() const
{
    return decodeImageSource_;
}

void ImageKnifeTaskInternal::SetDesiredSize(Image_Size desiredSize)
{
    desiredImageSize_ = desiredSize;
}

void ImageKnifeTaskInternal::MarkDecodeFrameFinished()
{
    isDecodeFrameFinished_ = true;
}

bool ImageKnifeTaskInternal::IsDecodeFrameFinished() const
{
    return isDecodeFrameFinished_;
}

int ImageKnifeTaskInternal::GetDecodeFrameIndex() const
{
    if (!isFrameDecodeMode_ && isAnimationImage_) {
        return -1;
    }
    return frameIndex_;
}

bool ImageKnifeTaskInternal::IsFrameDecodeMode() const
{
    return isFrameDecodeMode_;
}

void ImageKnifeTaskInternal::SetFileTypeInfo(std::shared_ptr<FileTypeInfo> fileTypeInfo)
{
    fileTypeInfo_ = fileTypeInfo;
}

std::shared_ptr<FileTypeInfo> ImageKnifeTaskInternal::GetFileTypeInfo() const
{
    return fileTypeInfo_;
}

void ImageKnifeTaskInternal::CheckDecodeMode()
{
    if (fileTypeInfo_ == nullptr || fileTypeInfo_->frameCount <= 1) {
        return;
    }
    isAnimationImage_ = true;

    // animator组件必须使用pixelmap列表，即不支持逐帧解码
    if (isAnimator_) {
        return;
    }

    if (fileTypeInfo_->width == 0 || fileTypeInfo_->height == 0) {
        return;
    }

    IMAGE_KNIFE_CHECK(request_ == nullptr);
    auto option = request_->GetImageKnifeOption();
    IMAGE_KNIFE_CHECK(option == nullptr);

    const size_t maxSize =  720 * 720 * 32;
    uint32_t imageSize = fileTypeInfo_->width * fileTypeInfo_->height * fileTypeInfo_->frameCount;
    if (option->animationDecodeMode == AnimationDecodeMode::FRAME_MODE ||
        (option->animationDecodeMode == AnimationDecodeMode::AUTO && (imageSize > maxSize))) {
        // 确认解码模式
        isFrameDecodeMode_ = true;
        auto dataCache = std::make_shared<ImageDataCacheInternal>(product.imageBuffer, product.imageLength,
            isDefaultDecodeSource_, option, fileTypeInfo_);
        dataCache->requestType = type_;
        product.imageDataCache = dataCache;
    }
}

void ImageKnifeTaskInternal::QueryImageBufferFormat()
{
    IMAGE_KNIFE_CHECK(request_ == nullptr);
    if (product.imageBuffer == nullptr) {
        EchoError("Empty Image Buffer (Query Image Format)");
        return;
    }

    // 先使用自定义的判断逻辑
    auto fileTypeParser = ImageKnifeInternal::GetInstance().GetFileTypeParser();
    if (fileTypeParser != nullptr) {
        decodeImageSource_ = fileTypeParser->CreateDecodeImageSource(product.imageBuffer.get(), product.imageLength);
        fileTypeInfo_ = fileTypeParser->ParseFileTypeInfo(product.imageBuffer.get(), product.imageLength,
                                                          decodeImageSource_);
    }
    // 使用默认的格式判断逻辑
    if (fileTypeInfo_ == nullptr || fileTypeInfo_->format == ImageFormat::UNKNOWN) {
        isDefaultDecodeSource_ = true;
        auto imageSource = std::make_shared<DecodeImageSourceDefault>(product.imageBuffer.get(), product.imageLength);
        fileTypeInfo_ = FileTypeParserDefault::GetInstance().ParseFileTypeInfo(product.imageBuffer.get(),
                                                                               product.imageLength, imageSource);
        std::string errorInfo = imageSource->GetErrorInfo();
        if (!errorInfo.empty()) {
            EchoError(errorInfo);
            if (type_ == ImageRequestType::MAIN_SRC) {
                request_->GetImageInfo().errorInfo.code = LoadFailedCode::IMAGE_SOURCE_ERROR;
            }
            decodeImageSource_ = nullptr;
            return;
        }
        decodeImageSource_ = imageSource;
    } else if (decodeImageSource_ == nullptr && fileTypeInfo_->format != ImageFormat::CUSTOM_FORMAT) {
        // 用户判断了非自定义格式，但没有创建对应imageSource，根据type进行create
        isDefaultDecodeSource_ = true;
        auto imageSource = std::make_shared<DecodeImageSourceDefault>(product.imageBuffer.get(), product.imageLength);
        if (fileTypeInfo_->format == ImageFormat::AVIF) {
            imageSource->CreateDecoderAvif();
        } else {
            imageSource->CreateImageSourceNative();
        }
        decodeImageSource_ = imageSource;
    }

    if (fileTypeInfo_ == nullptr || fileTypeInfo_->format == ImageFormat::UNKNOWN) {
        EchoError("Failed To Parse ImageInfo");
        return;
    }

    CheckDecodeMode();
}

void ImageKnifeTaskInternal::SetRequestImageInfo()
{
    if (fileTypeInfo_ == nullptr) {
        return;
    }
    Image_Size imageSize = request_->GetRequestImageSize();
    if (type_ == ImageRequestType::MAIN_SRC) {
        // 请求数据采集，记录主图信息。buffer size在loading结束后记录
        IMAGE_KNIFE_CHECK(request_ == nullptr);
        request_->GetImageInfo().imageHeight = fileTypeInfo_->height;
        request_->GetImageInfo().imageWidth = fileTypeInfo_->width;
        request_->GetImageInfo().type = fileTypeInfo_->format;
        request_->GetImageInfo().frameCount = fileTypeInfo_->frameCount;
        request_->GetImageInfo().customFormat = fileTypeInfo_->customFormat;

        // 记录请求时的组件宽高
        request_->GetImageInfo().componentWidth = imageSize.width;
        request_->GetImageInfo().componentHeight = imageSize.height;
        // 降采样，解码期望宽高计算
        auto option = request_->GetImageKnifeOption();
        IMAGE_KNIFE_CHECK(option == nullptr);
        desiredImageSize_ = DownSampler::CalculateSize(fileTypeInfo_->format,
                                                       {.width = fileTypeInfo_->width, .height = fileTypeInfo_->height},
                                                       imageSize, option->downSampling);
        IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s DownSampling Strategy:%{public}d Desired Size: %{public}d, %{public}d",
                        GetTaskInfo().c_str(), static_cast<int>(option->downSampling),
                        desiredImageSize_.width, desiredImageSize_.height);
    }

    // 设置svg期望尺寸为组件测算尺寸
    if (fileTypeInfo_->format == ImageFormat::SVG) {
        if (imageSize.width != 0 && imageSize.height != 0) {
            desiredImageSize_ = imageSize;
        } else {
            desiredImageSize_.width = fileTypeInfo_->width;
            desiredImageSize_.height = fileTypeInfo_->height;
        }
        IMAGE_KNIFE_LOG(LOG_DEBUG, "%{public}s Set Svg Desired Size: %{public}u, %{public}u",
                        GetTaskInfo().c_str(), desiredImageSize_.width, desiredImageSize_.height);
    }
}

std::shared_ptr<ImageKnifeRequestInternal> ImageKnifeTaskInternal::GetImageKnifeRequestInternal() const
{
    return request_;
}

OH_ImageSourceNative *ImageKnifeTaskInternal::GetImageSourceNative() const
{
    auto imageSource = std::dynamic_pointer_cast<DecodeImageSourceDefault>(decodeImageSource_);
    if (imageSource == nullptr) {
        return nullptr;
    }

    return imageSource->GetImageSourceNative();
}

ImageKnifeDecoderAvif *ImageKnifeTaskInternal::GetAvifDecoder() const
{
    auto imageSource = std::dynamic_pointer_cast<DecodeImageSourceDefault>(decodeImageSource_);
    if (imageSource == nullptr) {
        return nullptr;
    }
    return imageSource->GetAvifDecoder();
}

Image_Size ImageKnifeTaskInternal::GetDesiredImageSize() const
{
    return desiredImageSize_;
}

void ImageKnifeTaskInternal::SetFallbackUrl(std::string fallbackUrl)
{
    fallbackUrl_.SetString(fallbackUrl);
    imageSrc_ = &fallbackUrl_;
}

void ImageKnifeTaskInternal::ResetFallbackUrl()
{
    fallbackUrlIndex = -1;
    imageSrc_ = imageSrcBack_;
}

bool ImageKnifeTaskInternal::IsFileCacheNeedRename() const
{
    return fileCacheNeedRename_;
}

void ImageKnifeTaskInternal::MarkFileCacheNeedRename()
{
    fileCacheNeedRename_ = true;
}
} // end of namespace
